import http from '@/utils/http'
import Vue from 'vue'
// 获取广告信息
export function getExamAd(params) {
  return http.get('/webapi/api/exam_banner', params)
}
// 获取某个问题
export function getOneQuestion(params) {
  return http.post('/wxpub/api/question', params)
}
// 上报做题进度
export function uploadProgress(params) {
  return http.post('/storage/question/progress', params)
}
// 获取滑块验证码
export function sliderCode(params) {
  return http.get('/app/slider_verification/slider_code', params)
}
// 滑块验证码校验
export function verifySlider(params) {
  return http.post('/app/slider_verification/verify_slider', params)
}
// 滑块验证码校验
export function recordWrong(params) {
  let { questions = [] } = params
  let controller = getControllerByExamClassify(questions)
  return http.post(`/storage/${controller}/add_wrong`, params)
}
export function addCollect(params) {
  return http.post('/storage/question/add_collect', params)
}
export function deleteCollect(params) {
  return http.post('/storage/question/delete_collect', params)
}
// 删除错题
export function deleteWrong(params) {
  return http.post('/storage/question/delete_wrong', params)
}
export function errorReport(params) {
  return http.post('/wxpub/api/error_report', params)
}

/**
 * [getExamQuestion 获取试题信息]
 * @params {[Number]}  exam_id [试题id]
 * @return {[Object]} [解析好后的试题数据]
 */
export function getExamQuestion(params, examType = 'cpa') {
  //每次进来优先从缓存中取
  // let resCache = storage.get(`question_${params.exam_id}`)
  // let resCacheExpire = storage.get(`question_${params.exam_id}_expire`)

  // //本地有缓存
  // if (resCache && resCacheExpire) {
  //   try {
  //     //如果超过了2个小时，清除本地缓存，重新从接口取
  //     if (Date.now() > resCacheExpire) {
  //       storage.remove(`question_${params.exam_id}`)
  //       storage.remove(`question_${params.exam_id}_expire`)
  //       throw new Error()
  //     }

  //     return Promise.resolve(JSON.parse(resCache))
  //   } catch (e) {
  //     /*如果出错，就继续走下面的流程*/
  //   }
  // }

  //如果没有缓存或者缓存数据有误，就调接口
  return http.get('/wxpub/api/exam_question', params).then(res => {
    res = parseExamData(res.data, examType)
    //缓存解析后  的数据，下次直接使用
    // storage.set(`question_${params.exam_id}`, JSON.stringify(res))
    // storage.set(
    //   `question_${params.exam_id}_expire`,
    //   Date.now() + 2 * 3600 * 1000
    // )
    return res
  })
}
// 获取万人模考试题
export function getMockExamInfo(params) {
  return http.get('/wxpub/examination/exam_info', params).then(res => {
    const { data } = res.data
    res = parseExamData(data)
    return res
  })
}
// 提交万人模考结果
export function postMockExamResult(params) {
  return http.post('/wxpub/examination/submit_exam', params)
}
// 获取万人模考结果
export function getMockExamResult(params) {
  return http.get('/wxpub/examination/exam_answer', params)
}
/**
 *
 * @param {subject_id,exam_id, exam_type} params
 * @returns
 */
export function getProgress(params) {
  return http
    .get('/storage/question/progress', Object.assign(params, { v: 'v2' }))
    .then(res => {
      if (res.errcode !== 0) {
        return Vue.prototype.$message({
          type: 'error',
          message: '进度同步失败，使用本地进度'
        })
      }
      let { collect, progress, ref, new_ref, is_view, max_duration } = res.data
      let { exam_id } = params
      let {
        data,
        progressStr,
        is_view: is_new_view,
        collects,
        max_duration: maxDuration,
        new_ref: is_new_ref
      } = parseProgress(
        progress,
        true,
        new_ref,
        exam_id,
        is_view,
        collect,
        max_duration
      )
      // console.log(progress)
      //将试题进度缓存在本地，每次调用时与远程合并
      storage.set(
        `questionProgress_${exam_id}`,
        JSON.stringify({
          progressStr,
          ref,
          new_ref: is_new_ref,
          lastIndex: data.length ? data.length - 1 : 0
        })
      )

      // 缓存一份收藏到本地
      storage.set(`collect_${exam_id}`, JSON.stringify(collects))

      return {
        is_view: is_new_view,
        max_duration: maxDuration,
        parseProgressData: data,
        progressStr,
        collect: Object.keys(collects),
        old_collect: collects
      }
    })
    .catch(e => {
      console.log(e)
      Vue.prototype.$message({
        type: 'error',
        message: '同步云端进度失败，当前使用本地进度'
      })
      let cacheKey = `questionProgress_` + params.exam_id
      let localProgressCache = JSON.parse(storage.get(cacheKey))

      let { progressStr: localStr, ref: localRef } = localProgressCache
      let { data, progressStr } = parseProgress(
        localStr,
        true,
        localRef,
        params.exam_id
      )
      return {
        parseProgressData: data,
        progressStr
      }
    })
}
export function saveExamProgress(params) {
  return http.post('/storage/question/progress', params)
}
// 清空进度
export function clearExamProgress(params) {
  return http.post('/storage/question/clear_exam_progress', params)
}
export function resetExam(params) {
  return http.post('/wxpub/examination/reset_exam', params)
}
// 私教学习中心提交做题结果后端统计
export function submitQuestionRecord(params) {
  return http.post('/ban/private_study/question_bank/add_record', params)
}
/**
 * saveAnswerCount 保存用户做题正确和错误的数量
 * @param {[string]} from
 * @param {[object]} question_map r:正确数量  w:错误数量
 */
export function saveAnswerCount(params) {
  return http.post('/storage/question/exam_statistics', params)
}
// 获取某天某科目题库
export function getPlanQuestions(params) {
  return http.get('/storage/learnplan/questions', params).then(res => {
    let { data } = res
    let knowledges = data.knowledges
    data = formatPlanExamData(data)
    data = parseExamData(data)
    data.knowledges = knowledges
    return data
  })
  // return http.get('/storage/learnplan/questions', params)
}

export function getPlanExamData(params) {
  return http.get('/storage/learnplan/questions', params)
}

// ******************公共函数***************

/**
 * [parseExamData 接口数据]
 * @param  {[Object]} res [接口数据]
 * @return {[Object]} res   [处理后的接口数据]
 */
function parseExamData(res, examType = 'cpa') {
  if (!res.parts || !res.parts.length) {
    res.parts = []
    res.questionsList = []
    return res
  }

  //获取考试模式
  let examModel = +res.paper_type
  // 对应中文数字标号
  let listTitleNumMap = {
    0: '一',
    1: '二',
    2: '三',
    3: '四',
    4: '五'
  }
  //整合所有试题
  res.questionsList = []
  //解析接口数据
  let count = 0
  res.parts = res.parts.map((part, partIndex) => {
    let { questions, title = '', condition, description } = part
    //处理标题，因为后台返回的标题乱七八糟！！！
    //['判断题','第二部分：多项选择题','四、不定性选择（本类题共15小题，每小题2分，共30分）']
    // let titleReg = /^[\u4e00-\u9fa5]+[：|、]?[\u4e00-\u9fa5]{2,5}/
    // let pies = title.match(titleReg)
    // if (pies && pies.length) {
    // title = pies[0]
    title = title.includes('、')
      ? title.split('、')[1]
      : title.includes('：')
      ? title.split('：')[1]
      : title
    // }
    title = listTitleNumMap[partIndex] + '、' + title
    let titleDescription = description
    let partQuestions = []

    //处理问题
    //后端定义的题型： 1-单选题，2-不定性选择题，3-综合题目（如阅读理解等一个题干多个子题），4-简答题
    //为了方便业务抽象组件，这里处理一下 1、单选、判断  2、多选 3-综合题目 4、简答  5、不定项
    //业务根据stem字段有没有值，来区分是否是综合题
    questions = questions.map((item, index) => {
      let {
        type: itemType,
        question_id,
        options,
        solution,
        answer,
        videos
      } = item
      ++count
      //把大题标题加在每项小题上
      item.title = title
      item.part_id = part.part_id //每个问题加上part_id，万人模考提交答案时使用
      item.titleDescription = titleDescription
      // 添加序号
      item.index = count
      // 添加标记字段
      item.marked = false
      // 添加在part中的位置(新增，兼容冲刺活动字段)
      item.part_index = index + 1
      switch (itemType) {
        //单选 + 判断
        case '1':
        //多项选择题
        case '2':
          //相当于第一版的ukey，后面统一叫索引id
          item.indexId = question_id + '_0'
          //保存所属部分的part，方便计分
          item.partIndex = `part_${partIndex}`
          //保存所属部分的part总分，方便计分
          item.partScore = part.score || 0

          item.stem = ''

          //处理选项、答案、解析
          try {
            item.options = JSON.parse(options)
          } catch (error) {}
          item.solution = solution
          item.answer = [...answer.split(',')]
          //1 - 练习模式  2 - 考试模式   3 - 背题模式
          item.questionModel = 1

          //处理视频
          if (videos) {
            try {
              item.videos = JSON.parse(videos)
            } catch (error) {}

            //处理"[[]]"这种数据，多条视频取第一条
            // item.videos = !videos.toString() ? null : videos[0]
          }

          partQuestions.push(item)
          break
        //综合题
        case '3':
        //简答题
        case '4':
          //一个题干对应多个题，抽象成多个题干多个题
          let parseArr = ['answer', 'options', 'videos', 'solution']
          parseArr.forEach(key => {
            try {
              if (item[key]) item[key] = JSON.parse(item[key])
            } catch (e) {}
          })
          //组合题options为数组
          if (Array.isArray(item.options) && item.options.length) {
            //相当于第一版的ukey，后面统一叫索引id
            // 给option 添加indexId
            item.options.forEach((option, optionIndex) => {
              option.indexId = `${question_id}_${optionIndex}`
            })
            item.indexId = question_id + '_0'
            //保存所属部分的part，方便计分
            item.partIndex = `part_${partIndex}`
            //保存所属部分的part总分，方便计分
            item.partScore = part.score || 0
            partQuestions.push(item)
          }
          //在中级考试中，综合题和简答题数据可能有问题
          //如 options="{}"    solution='xxxx' ，这个时候一道大题只能算一个小题，按小题处理
          if (isObject(item.options)) {
            item.indexId = question_id + '_0'
            item.partIndex = `part_${partIndex}`
            item.partScore = part.score || 0
            item.title = title
            item.stem = ''

            //处理选项、答案、解析
            item.options = ''
            item.answer = [answer]
            //1 - 练习模式  2 - 考试模式   3 - 背题模式
            item.questionModel = 1

            //处理视频
            if (item.videos) {
              //处理"[[]]"这种数据，多条视频取第一条
              // item.videos = !item.videos.toString() ? null : item.videos[0]
              try {
                // 单视频改为多视频
                item.videos = JSON.parse(videos)
              } catch (error) {
                item.videos = []
              }
            }
            partQuestions.push(item)
          }

          break
      }

      return item
    })
    //对所有题的额外处理
    //处理成 1、单选判断  2、多选  3、综合  4、简答  5、不定项
    partQuestions = partQuestions.map(item => {
      return mergeQuestion(item, part, examModel)
    })
    //所有题整合成一个大数组
    res.questionsList.push(...partQuestions)
    //下面是业务用于渲染答题卡
    return {
      title,
      description: part.description,
      questionCount: partQuestions.length,
      isSubjective: !!part.isSubjective,
      // type: itemType,
      //处理答题卡数据
      answerList: partQuestions.map(item => ({
        status: 'n', //做题状态，n - none 未答  h - half半对  r - right 正确  w - wrong 错误  d - done 已答
        indexId: item.indexId,
        marked: false,
        type: item.type,
        question_id: item.question_id
      })),
      questions,
      condition,
      hasCondition: condition ? true : false
    }
  })

  //  对于初级需要处理一下组合题的判分数据
  if (+res.paper_type === 2 && examType === 'exam') {
    if (!Array.isArray(res.questionsList) || !Array.isArray(res.parts)) return
    res.questionsList = res.questionsList.map(itema => {
      let { question_id, type } = itema
      if (+type !== 3) {
        return itema
      }

      res.parts.forEach(item => {
        let { questions, condition } = item
        if (condition && Array.isArray(questions)) {
          if (!Array.isArray(questions)) return
          questions.forEach(question => {
            if (question.question_id === question_id) {
              let { select_count, per_score, wrong_score } = condition
              itema.options = itema.options.map(itemb => {
                itemb.select_count = select_count
                itemb.wrongScore = wrong_score ? +wrong_score : 0
                itemb.perScore = per_score ? +per_score : 0
                return itemb
              })
            }
          })
        }
      })

      return itema
    })
  }

  return res
}
/**
 * [mergeQuestion 给每个问题加上类型，分数等]
 * @param  {[type]} item [question]
 * @return {[type]}      [item]
 */
function mergeQuestion(item, part, examModel) {
  let { condition, count, score } = part
  let { type, wrong_score, per_score, select_count = '' } = condition || {}
  //----如果没有condition，则认为是简答题，不判分
  //如果answer为空，则认为是简答题，不判分
  item.userAnswer = type === 3 ? '' : []

  switch (+item.type) {
    case 1:
      //单选或判断，需要区分是单选还是判断
      item.type = 1
      break
    case 2:
      //多选 或 不定项，其中不定项是在综合题中
      item.type = 2
      break
    case 3:
      //综合
      part.isSubjective = true
      item.type = 3
      item.userAnswer = Array.from({ length: item.answer.length }, () => [])
      break
    case 4:
      //简答
      part.isSubjective = true
      item.type = 4
      break
  }

  item.status = 'n'
  item.wrongScore = 0
  item.perScore = 0
  item.hasCollect = false //是否收藏
  item.hasRemoved = false //是否被移除错题
  // 特殊的判分逻辑，至少选择select_count个才得分，答案小于select_count不得分
  if (select_count) {
    item.select_count = select_count
  }

  //考试模式，判断condition，isComputedScore字段控制是否算分
  if (examModel === 2) {
    if ([1, 2, 5].includes(+item.type)) {
      item.isComputedScore = true
    }
    //每题的分数
    item.score = score / count

    // //处理判断题和不定项选择
    if (item.type === 2) {
      item.wrongScore = wrong_score ? +wrong_score : 0
      item.perScore = per_score ? +per_score : 0
    }
  } else {
    //练习模式，不判断condition，不打分
    item.isComputedScore = false
  }

  return item
}
function isObject(o) {
  return Object.prototype.toString.call(o) === '[object Object]'
}
//处理计划题目数据
function formatPlanExamData(res) {
  let obj = {
      exam_type: '1'
    },
    single = [],
    multiple = [],
    judge = [],
    random = [],
    shortAnswer = [],
    singleObj = {},
    multipleObj = {},
    judgeObj = {},
    randomObj = {},
    shortAnswerObj = {}
  res.questions.forEach(item => {
    item.question_id = item.id
    switch (item.type) {
      case '1':
        if (item.options.includes('"C":')) {
          single.push(item)
        } else {
          judge.push(item)
        }
        break
      case '2':
        multiple.push(item)
        break
      case '3':
        random.push(item)
        break
      case '4':
        shortAnswer.push(item)
        break
    }
  })
  obj.parts = []
  if (single.length > 0) {
    singleObj = {
      title: '单项选择题',
      description: '',
      count: single.length,
      questions: single
    }
    obj.parts.push(singleObj)
  }
  if (multiple.length > 0) {
    multipleObj = {
      title: '多项选择题',
      description: '',
      count: multiple.length,
      questions: multiple
    }
    obj.parts.push(multipleObj)
  }
  if (judge.length > 0) {
    judgeObj = {
      title: '判断题',
      description: '',
      count: judge.length,
      questions: judge
    }
    obj.parts.push(judgeObj)
  }
  if (random.length > 0) {
    randomObj = {
      title: '不定项选择题',
      description: '',
      count: random.length,
      questions: random
    }
    obj.parts.push(randomObj)
  }
  if (shortAnswer.length > 0) {
    shortAnswerObj = {
      title: '简答题',
      description: '',
      count: shortAnswer.length,
      questions: shortAnswer
    }
    obj.parts.push(shortAnswerObj)
  }
  return obj
}
//通过题库的exam_classify字段，获取接口的命名空间
function getControllerByExamClassify(questions = [], defaultCtrl = 'question') {
  let controller = defaultCtrl
  //从param.questions中获取是否包含了exam_classify字段，如果包含，则根据exam_classify来决定调哪个模块的错题上报接口
  try {
    if (questions.length) {
      let { exam_classify } = questions[0]

      switch (+exam_classify) {
        case 1:
          controller = 'smart' //智能题库
          break
      }
    }
  } catch (error) {
    console.warn(`错题上报错误：${error.toString()}`)
  }

  return controller
}
/**
 * 端同步需要对比使用优先级
 * @param {*} new_ref 优先级值
 * @param {*} examId 试题id
 * **/
function handlerServeProgress(new_ref, examId, str) {
  let cacheKey = `questionProgress_` + examId
  let localProgressCache = {}
  try {
    localProgressCache = JSON.parse(storage.get(cacheKey)) || {}
  } catch (e) {
    localProgressCache = {}
  }
  let { new_ref: localRef, progressStr: localStr } = localProgressCache
  // 本地没有或者比远程的小，直接使用远程的
  let isUseServe =
    !localRef || (new_ref && localRef && new_ref > localRef) ? true : false
  if (+new_ref === 0 && str === '[]') {
    isUseServe = false
  }

  // remoteProgress.forEach(item => progress.push(item))

  return {
    isUseServe,
    localStr,
    localRef
  }
}
/**
 * [parseProgress 解析当前试题的进度]
 * @param  {[String]} str [接口返回的progress字段]
 * @param  {[Boolean]} needMerge [是否需要与本地的进度合并]
 * @param  {[Number]} ref [远程的标记，如果远程标记与本地标记不一致，说明远程清除过进度，则其他端也需要清除，直接清理本地，使用远程]
 * @param  {[String]} examId [试题id]
 * @param  {[Number]} is_view [是否交卷 0-未交卷 1-已交卷]
 * @param  {[Object]} collect [收藏数据]
 * @return {[type]}     [处理完成后的进度数组]
 */
function parseProgress(
  str,
  needMerge = false,
  new_ref,
  examId,
  is_view,
  collect,
  maxDuration
) {
  str = str || '[]'
  //合并本地与远程进度
  let { isUseServe, localStr, localRef } = handlerServeProgress(
    new_ref,
    examId,
    str
  )

  if (needMerge) {
    str = isUseServe ? str : localStr
  }

  let data = []
  try {
    let res = JSON.parse(str)
    data = res.map(item => {
      let { t, id } = item
      let cacheObj = { id, status: t }
      //兼容答案末尾带了个，
      if (!item[t]) {
        cacheObj.status = 'n'
        cacheObj.userAnswer = []
        return cacheObj
      }
      item[t] = item[t].toString().replace(/,$/gi, '')
      switch (t) {
        //正确错误半对，直接赋值
        case 'r':
        case 'w':
        case 'h':
          cacheObj.userAnswer = item[t].split(',')
          break
        case 'n':
          cacheObj.userAnswer = []
          break
        case 'd':
          // 简答题，小题答案以字符串显示
          cacheObj.userAnswer = item[t]
          break
      }
      return cacheObj
    })
  } catch (e) {}

  // 获取本地的收藏数据
  let collects = storage.get(`collect_${examId}`) || '{}'
  try {
    collects = JSON.parse(collects)
  } catch (e) {
    collects = {}
  }

  // 本地用时
  let localDuration = storage.get(`timeConsuming_${examId}`) || 0

  // 本地的是否打开过报告页
  let isviewLocal = storage.get(`isGoReport_${examId}`) || 0

  console.log(`使用的${isUseServe ? '远程' : '本地'}进度`)
  return {
    data,
    progressStr: str,
    is_view: isUseServe ? is_view : isviewLocal,
    collects: isUseServe ? collect : collects,
    max_duration: isUseServe ? maxDuration : localDuration,
    new_ref: isUseServe ? new_ref : localRef
  }
}
//评论相关接口
/**
 * [getExamComments 获取试题的评论信息]
 * @params {[String]}  from [wxpub 请求来自微信]
 * @params {[Number]}  exam_id [试题所属试卷id]
 * @params {[String]}  subject_id [科目Id]
 * @params {[Number]}  exam_type [试卷类型]
 * @params {[String]}  ukeys [问题数组，点哪一道题请求哪道]
 */
export function getExamComments(params) {
  return http.post('/storage/comment/exam', params)
}
/**
 * [getSingleExamComments 获取单个试题的评论信息]
 * @params {[String]}  ukey [indexId，点哪一道题请求哪道]
 * @params {[String]}  object_id [评论id]
 */
export function getSingleExamComments(params) {
  return http.post('/storage/comment/personal', params)
}

/**
 * [getMoreExamComments 获取试题更多评论信息]
 * @params {[String]}  from [wxpub 请求来自微信]
 * @params {[Number]}  exam_id [试题所属试卷id]
 * @params {[String]}  subject_id [科目Id]
 * @params {[Number]}  exam_type [试卷类型]
 * @params {[String]}  ukey [对应试题的ukey]
 * @params {[Number]}  start [分页开始]
 * @params {[Number]}  end [分页结束]
 */
export function getMoreExamComments(params) {
  return http.get('/storage/comment/question', params)
}

/**
 * [saveExamComment 保存评论信息]
 * @params {[String]}  ukey [要问的试题indexId]
 * @params {[Number]}  exam_id [试题所属试卷id]
 * @params {[String]}  subject_id [科目Id]
 * @params {[Number]}  exam_type [试卷类型]
 * @params {[String]}  comment [评论内容]
 * @params {[String]}  reply_nickname [被回复人昵称]
 * @params {[String]}  reply_object_id [被回复评论id，只在评论第二层数据时传入]
 * @params {[Number]}  object_id [被回复的评论id，评论第二层数据时，该字段是顶层评论的id]
 * @params {[Number]}  comment_type [评论类型 1 - 点赞别人的讨论  2 - 新增评论  3 - 回复别人  4 - 取消点赞]
 */
export function saveExamComment(params) {
  return http.post('/storage/comment/question', params)
}

// 上报错题本：做正确的问题
export function postWrongProgress(params) {
  return http.post('/storage/question/wrong_progress', params)
}

// 笔记列表
export function getUserNotes(params) {
  return http.get('/wxpub/api_base/user_note_exam', params)
}

// 新增笔记
export function postUserNote(params) {
  return http.post('/wxpub/api_base/user_note_exam', params)
}

// 删除笔记
export function deleteNote(params) {
  return http.post('/wxpub/api_base/delete_note_exam', params)
}
// 视频解析评价相关
export function uploadQuestionEvaluate(params) {
  return http.post('/wxpub/exam/question_evaluate', params)
}
export function getQuestionEvaluate(params) {
  return http.get('/wxpub/exam/question_evaluate_info', params)
}
